package com.mbengue.corp.artisan.controleur;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.mbengue.corp.artisan.dao.ArticleDao;
import com.mbengue.corp.artisan.dao.ArticleFeuilleDao;
import com.mbengue.corp.artisan.dao.ClientDao;
import com.mbengue.corp.artisan.dao.FeuilleDao;
import com.mbengue.corp.artisan.modele.Article;
import com.mbengue.corp.artisan.modele.ArticlesFeuille;
import com.mbengue.corp.artisan.modele.Client;
import com.mbengue.corp.artisan.modele.Devis;
import com.mbengue.corp.artisan.modele.Facture;
import com.mbengue.corp.artisan.modele.Feuille;
import com.mbengue.corp.artisan.utils.IdGenerateur;
import com.mbengue.corp.artisan.utils.TypeComposant;

public class Controleur {
  /*@Autowired
  private IPersistenceManager manageur;
  @Autowired
  private Ajouteur ajouteur;
  @Resource
  private Trouveur trouveur;
  @Autowired
  private Modifieur modifieur;
  @Autowired
  private Supprimeur supprimeur;*/
  @Autowired
  private ArticleDao articleDao;
  @Autowired
  private ArticleFeuilleDao articleFeuilleDao;
  @Autowired
  private ClientDao clientDao;
  @Autowired
  private FeuilleDao feuilleDao;

  public Controleur() {
    /*this.manageur = new PersistenceManager();
    this.ajouteur = new Ajouteur(manageur);
    this.trouveur = new Trouveur(manageur);
    this.modifieur = new Modifieur(manageur);
    this.supprimeur = new Supprimeur(manageur, trouveur);*/
  }

  /*public Ajouteur getAjouteur() {
    return ajouteur;
  }

  public Trouveur getTrouveur() {
    return trouveur;
  }

  public Modifieur getModifieur() {
    return modifieur;
  }

  public Supprimeur getSupprimeur() {
    return supprimeur;
  }

  public void setManageur(IPersistenceManager manageur) {
    this.manageur = manageur;
  }

  public void setAjouteur(Ajouteur ajouteur) {
    this.ajouteur = ajouteur;
  }

  public void setTrouveur(Trouveur trouveur) {
    System.out.println("*******************************************");
    System.out.println("******** Mise a jour du trouveur ...*******");
    System.out.println("*******************************************");
    this.trouveur = trouveur;
  }

  public void setModifieur(Modifieur modifieur) {
    this.modifieur = modifieur;
  }

  public void setSupprimeur(Supprimeur supprimeur) {
    this.supprimeur = supprimeur;
  }*/

  public Article trouverArticle(String code) {
    return this.articleDao.trouverArticleParCode(code);
  }

  public List<String> tousLesCodesArticle() {
    return this.articleDao.tousLesCodesArticle();
  }

  public String getDesignationArticle(String code) {
    return this.articleDao.getDesignationArticle(code);
  }

  public List<Article> tousLesArticles(String[] articleCodes) {
    return this.articleDao.tousLesArticles(articleCodes);
  }

  public Facture creerFacture(List<Object> donneesCourantes, Client client) {
    if (donneesCourantes == null || donneesCourantes.size() <= 0) {
      return null;
    }

    Facture facture = new Facture();
    creerFeuille(facture, client, donneesCourantes);
    this.feuilleDao.modifierFeuille(facture);

    return facture;
  }

  public Devis creerDevis(List<Object> donneesCourantes, Client client) {
    if (donneesCourantes == null || donneesCourantes.size() <= 0) {
      return null;
    }

    Devis devis = new Devis();
    creerFeuille(devis, client, donneesCourantes);
    this.feuilleDao.modifierFeuille(devis);

    return devis;
  }

  private void creerFeuille(Feuille feuille, Client client, List<Object> articles) {
    if (articles == null || articles.size() <= 0) {
      return;
    }

    if (feuille instanceof Facture) {
      feuille.setNumero(IdGenerateur.nouveauFactureId());
    } else {
      feuille.setNumero(IdGenerateur.nouveauDevisId());
    }

    feuille.setDate(new Date());
    feuille.setArtisan("AB Latif");
    feuille.setClient(client);
    this.feuilleDao.ajouterFeuille(feuille);
    for (Object obj : articles) {
      Article article = (Article) obj;
      feuille.majMontant(article, true);
      ArticlesFeuille artFeu = new ArticlesFeuille();
      artFeu.setArticle(article);
      artFeu.setFeuille(feuille);
      this.articleFeuilleDao.ajouterArticleFeuille(artFeu);
    }
  }

  public void ajouterClients(List<Client> clients) {
    if (clients == null || clients.size() <= 0) {
      return;
    }

    for (Client client : clients) {
      this.clientDao.ajouterClient(client);
    }
  }

  public void ajouterArticles(List<Article> articles) {
    if (articles == null || articles.size() <= 0) {
      return;
    }

    for (Article article : articles) {
      this.articleDao.ajouterArticle(article);
    }
  }

  @SuppressWarnings("rawtypes")
  public List toutesLesFactures() {
    return this.feuilleDao.toutesLesFactures();
  }

  @SuppressWarnings("rawtypes")
  public List tousLesDevis() {
    return this.feuilleDao.tousLesDevis();
  }

  public List<Article> tousLesArticles() {
    return this.articleDao.tousLesArticles();
  }

  public List<Client> tousLesClients() {
    return this.clientDao.tousLesClients();
  }

  public Client trouverClientParNumero2Telephone(String telephone) {
    return this.clientDao.trouverClientParNumeroTelephone(telephone);
  }

  public Facture trouverFacture(String numero) {
    return (Facture) this.feuilleDao.trouverFeuilleParNumero(TypeComposant.FACTURE.getNom(), numero);
  }

  public Object[][] tousLesArticlesD1Facture(String numeroFacture) {
    List<Article> articles = this.articleFeuilleDao.tousLesArticlesD1Facture(numeroFacture);
    return this.tableauArticles(articles);
  }

  private Object[][] tableauArticles(List<Article> articleList) {
    if (articleList.size() <= 0) {
      return new Object[0][];
    }

    Object[][] articles = new Object[articleList.size()][];
    for (int i = 0; i < articleList.size(); i++) {
      articles[i] = articleList.get(i).toArray();
    }
    return articles;
  }

  public List<Client> trouverClientNomOuPrenom(String nom) {
    if (nom == null || nom.equals("")) {
      return null;
    }
    return this.clientDao.trouverClientParNomPrenom(nom, nom);
  }

  public List<Article> trouverArticlesParCode(String code) {
    return this.articleDao.trouverArticlesParCode(code);
  }

  public String[] tousLesNomsClients() {
    return this.clientDao.tousLesNomsClients().toArray(new String[0]);
  }

  @SuppressWarnings("rawtypes")
  public List trouverFeuilleParDates(String type, Date dateDebut, Date dateFin) {
    if(type.equals(TypeComposant.FACTURE.getNom())) {
      return this.feuilleDao.trouverFacturesParDates(new Timestamp(dateDebut.getTime()),
          new Timestamp(dateFin.getTime()));
    }
    return this.feuilleDao.trouverDevisParDates(new Timestamp(dateDebut.getTime()), new Timestamp(dateFin.getTime()));
  }

  public List<Feuille> trouverFeuillesParClient(String nom, String prenom) {
    List<Client> clients = this.clientDao.trouverClientParNomEtPrenom(nom, prenom);
    List<Feuille> feuilles = new ArrayList<Feuille>();
    for (Client client : clients) {
      feuilles.addAll(this.feuilleDao.trouverFeuillesParClient(client));
    }
    return feuilles;
  }

  public List<Feuille> trouverFeuillesParNumero(String type, String numero) {
    return this.feuilleDao.trouverFeuillesParNumero(type, numero);
  }

  public void supprimerClient(Client client) throws Exception {
    List<Feuille> feuilles = this.trouverFeuillesParClient(client.getNom(), client.getPrenom());
    for (Feuille feuille : feuilles) {
      this.supprimerFeuille(feuille);
    }
    this.clientDao.supprimerClient(client);
  }

  public void supprimerFeuille(Feuille feuille) throws Exception {
    this.articleFeuilleDao.supprimerJointureParFeuille(feuille);
    this.feuilleDao.supprimerFeuille(feuille);
  }

  public void supprimerArticle(Article article) throws Exception {
    this.articleFeuilleDao.supprimerJointureParArticle(article);
    this.articleDao.supprimerArticle(article);
  }

  public Client modifierClient(Client client) {
    this.clientDao.modifierClient(client);
    return client;
  }

  public Article modifierArticle(Article article) {
    Article art = this.trouverArticle(article.getCode());
    List<Feuille> feuilles = this.articleFeuilleDao.toutesLesFeuillesD1Article(art);

    for (Feuille feuille : feuilles) {
      feuille.majMontant(art, false);
      feuille.majMontant(article, true);
      this.feuilleDao.modifierFeuille(feuille);
    }

    this.articleDao.modifierArticle(article);
    return article;
  }

  public List<Article> tousLesArticlesD1Feuille(Feuille feuille) {
    return this.articleFeuilleDao.tousLesArticlesD1Feuille(feuille.getNumero());
  }

  public void modifierFeuille(Feuille feuille, List<Article> articles, boolean ajoutOuSuppression) {
    ArticlesFeuille artFeu;
    if (ajoutOuSuppression) {
      for (Article article : articles) {
        feuille.majMontant(article, true);
        artFeu = new ArticlesFeuille();
        artFeu.setArticle(article);
        artFeu.setFeuille(feuille);
        articleFeuilleDao.ajouterArticleFeuille(artFeu);
      }
    } else {
      for (Article article : articles) {
        feuille.majMontant(article, false);
        artFeu = articleFeuilleDao.trouverArticleFeuille(feuille, article);
        articleFeuilleDao.supprimerArticleFeuille(artFeu);
      }
    }
    this.feuilleDao.modifierFeuille(feuille);
  }
}
